/*
 * bmp-tools.c
 *
 *  Created on: May 21, 2013
 *      Author: koldar
 */

#include "graphbmp-tools.h"

//colori disponibili per il passaggio di un camion
static RGB colorSet[]={COLOR_RED,COLOR_GREEN,COLOR_BLUE,COLOR_ORANGE,COLOR_CIAN,COLOR_VIOLET};
//colori disponibili per il soddisfacimento di un camion
static RGB gcolorSet[]={COLOR_DARK_RED,COLOR_DARK_GREEN,COLOR_DARK_BLUE,COLOR_DARK_ORANGE,COLOR_DARK_CIAN,COLOR_DARK_VIOLET};


void topLine(Pimage img,int x,int y,int width,int height,int radius,RGB color){
	drawLine(img,x-width/2,y-height/2,x+width/2,y-height/2,radius,color);
}
void middleLine(Pimage img,int x,int y,int width,int height,int radius,RGB color){
	drawLine(img,x-width/2,y,x+width/2,y,radius,color);
}
void bottomLine(Pimage img,int x,int y,int width,int height,int radius,RGB color){
	drawLine(img,x-width/2,y+height/2,x+width/2,y+height/2,radius,color);
}
void topLeftLine(Pimage img,int x,int y,int width,int height,int radius,RGB color){
	drawLine(img,x-width/2,y-height/2,x-width/2,y,radius,color);
}
void topRightLine(Pimage img,int x,int y,int width,int height,int radius,RGB color){
	drawLine(img,x+width/2,y-height/2,x+width/2,y,radius,color);
}
void bottomLeftLine(Pimage img,int x,int y,int width,int height,int radius,RGB color){
	drawLine(img,x-width/2,y,x-width/2,y+height/2,radius,color);
}
void bottomRightLine(Pimage img,int x,int y,int width,int height,int radius,RGB color){
	drawLine(img,x+width/2,y,x+width/2,y+height/2,radius,color);
}


void drawDigit(Pimage img,int digit,int x,int y,int width,int height,int radius,RGB color){
	switch (digit){
	case 0:{
		topLine(img,x,y,width,height,radius,color);
		topLeftLine(img,x,y,width,height,radius,color);
		topRightLine(img,x,y,width,height,radius,color);
		bottomLeftLine(img,x,y,width,height,radius,color);
		bottomRightLine(img,x,y,width,height,radius,color);
		bottomLine(img,x,y,width,height,radius,color);
		return;
	}
	case 1:{
		topRightLine(img,x,y,width,height,radius,color);
		bottomRightLine(img,x,y,width,height,radius,color);
		return;
	}
	case 2: {
		bottomLine(img,x,y,width,height,radius,color);
		bottomLeftLine(img,x,y,width,height,radius,color);
		middleLine(img,x,y,width,height,radius,color);
		topRightLine(img,x,y,width,height,radius,color);
		topLine(img,x,y,width,height,radius,color);
		return;
	}
	case 3: {
		bottomLine(img,x,y,width,height,radius,color);
		bottomRightLine(img,x,y,width,height,radius,color);
		middleLine(img,x,y,width,height,radius,color);
		topRightLine(img,x,y,width,height,radius,color);
		topLine(img,x,y,width,height,radius,color);
		return;
	}
	case 4: {
		bottomRightLine(img,x,y,width,height,radius,color);
		topRightLine(img,x,y,width,height,radius,color);
		middleLine(img,x,y,width,height,radius,color);
		topLeftLine(img,x,y,width,height,radius,color);
		return;
	}
	case 5: {
		bottomLine(img,x,y,width,height,radius,color);
		bottomRightLine(img,x,y,width,height,radius,color);
		middleLine(img,x,y,width,height,radius,color);
		topLeftLine(img,x,y,width,height,radius,color);
		topLine(img,x,y,width,height,radius,color);
		return;
	}
	case 6: {
		bottomLine(img,x,y,width,height,radius,color);
		bottomRightLine(img,x,y,width,height,radius,color);
		bottomLeftLine(img,x,y,width,height,radius,color);
		middleLine(img,x,y,width,height,radius,color);
		topLeftLine(img,x,y,width,height,radius,color);
		return;
	}
	case 7: {
		bottomRightLine(img,x,y,width,height,radius,color);
		topRightLine(img,x,y,width,height,radius,color);
		topLine(img,x,y,width,height,radius,color);
		return;
	}
	case 8: {
		bottomLeftLine(img,x,y,width,height,radius,color);
		bottomLine(img,x,y,width,height,radius,color);
		bottomRightLine(img,x,y,width,height,radius,color);
		middleLine(img,x,y,width,height,radius,color);
		topLeftLine(img,x,y,width,height,radius,color);
		topRightLine(img,x,y,width,height,radius,color);
		topLine(img,x,y,width,height,radius,color);
		return;
	}
	case 9: {
		bottomLine(img,x,y,width,height,radius,color);
		bottomRightLine(img,x,y,width,height,radius,color);
		middleLine(img,x,y,width,height,radius,color);
		topLeftLine(img,x,y,width,height,radius,color);
		topRightLine(img,x,y,width,height,radius,color);
		topLine(img,x,y,width,height,radius,color);
		return;
	}
	}
}

void drawNumber(Pimage img,int number,int digitgap, int x,int y,int width,int height,int radius,RGB color){
	int i;
	int cifre;
	if (number==0){
		cifre=1;
	}else{
		cifre=(int)floor(log10(number))+1;
	}
	//printf("%d %d\n",number,cifre);
	for (i=0;i<cifre;i++){
		drawDigit(img,(int)((number%((int)pow(10,cifre-i)))/(pow(10,cifre-i-1))),x+i*(digitgap+width),y,width,height,radius,color);
	}
}

void drawSolutionFromScratchDefaults(char* fileName, Psolution ps, int depotnode){
	drawSolutionFromScratch(
					fileName,
					ps,
					depotnode,
					15,
					10,
					7,
					1,
					4,
					2,
					1,
					COLOR_BLACK,
					COLOR_DARK_GREY,
					COLOR_VIOLET);
}

void drawSolutionFromScratch(char* filesName,Psolution solution,int depotnode,int nodeRadius,int nodeGap,int nodeNumberGap,int digitGap,int numberHeight,int NumberWidth,int numberRadius,RGB numberColor,RGB nodeColor, RGB depotColor){
	float graphRadius=(*(solution->gMatrix->N)+*(solution->gMatrix->N)%2)*(nodeRadius+nodeGap);
	int bmp_w=(int)(2*graphRadius+10*nodeRadius);
	int bmp_h=bmp_w;
	FILE* f=fopen(filesName,"w");
	writeHeaderInFile(f,bmp_h,bmp_w);
	Pimage img=initImage(bmp_w,bmp_h);
	fillColor(img,getRGB(255,255,255));

	//****************** disegno dei percorsi ************************
	int k;
	PedgeSol edge;
	PvehiclePath path;
	RGB color;
	for (k=0;k<*solution->K;k++){
		path=getVehiclePathInSolution(solution,k);
		resetMemory(path,DIRECTION_NEXT);
		while ((edge=getNearEdgeInVehiclePath(path,DIRECTION_NEXT))!=NULL){
			color=(amIGatheringEdge(solution->gMatrix,edge->id,k))?gcolorSet[k]:colorSet[k];
			drawNodeLine(img,*solution->gMatrix->N,graphRadius,edge->id->i,edge->id->j,edge->x,color);
		}
	}
	//******************** disegno dei nodi *************************
	drawNodes(img,*solution->gMatrix->N,graphRadius,nodeRadius,depotnode,nodeNumberGap,digitGap,numberHeight,NumberWidth,numberRadius,numberColor,nodeColor,depotColor);
	applyImageToFile(img,f);
	fclose(f);
	freeImage(img);
}

void drawSolution(FILE* f,Psolution solution,int depotnode,int nodeRadius,int nodeGap,int nodeNumberGap,int digitGap,int numberHeight,int NumberWidth,int numberRadius,RGB numberColor,RGB nodeColor, RGB depotColor){
	float graphRadius=*(solution->gMatrix->N)*(nodeRadius+nodeGap);
	int bmp_w=(int)(2*graphRadius+10*nodeRadius);
	int bmp_h=bmp_w;
	writeHeaderInFile(f,bmp_h,bmp_w);
	Pimage img=initImage(bmp_w,bmp_h);
	fillColor(img,getRGB(255,255,255));

	//****************** disegno dei percorsi ************************
	int k;
	PedgeSol edge;
	PvehiclePath path;
	for (k=0;k<*solution->K;k++){
		path=getVehiclePathInSolution(solution,k);
		resetMemory(path,DIRECTION_NEXT);
		while ((edge=getNearEdgeInVehiclePath(path,DIRECTION_NEXT))!=NULL){
			drawNodeLine(img,*solution->gMatrix->N,graphRadius,edge->id->i,edge->id->j,edge->x,colorSet[k]);
		}

	}
	//******************** disegno dei nodi *************************
	drawNodes(img,*solution->gMatrix->N,graphRadius,nodeRadius,depotnode,nodeNumberGap,digitGap,numberHeight,NumberWidth,numberRadius,numberColor,nodeColor,depotColor);

	applyImageToFile(img,f);
}



void drawNodes(Pimage img,int N,float graphradius,float noderadius, int depot,float nodenumbergap,int digitgap, int numberheight, int numberwidth, int numberradius,RGB numbercolor, RGB normalcolor,RGB depotcolor){
	int n;
	int x;
	int y;
	RGB color;
	for (n=0;n<N;n++){
		color=(n!=depot?normalcolor:depotcolor);
		getXYBMP(N,n,graphradius,img->width,img->height,&x,&y);
		drawNode(img,x,y,noderadius,color);
		getXYBMP(N,n,graphradius-nodenumbergap*noderadius,img->width,img->height,&x,&y);
		drawNumber(img,n+1,digitgap*noderadius,x,y,numberwidth*noderadius,numberheight*noderadius,numberradius,numbercolor);
	}
}

void getXYBMP(int N,int n,float graphradius,int widthBMP,int heightBMP,int* x, int*y){
	float angle=(2*M_PI)/N;
	*x=(int)(widthBMP/2+graphradius*cos(angle*n));
	*y=(int)(heightBMP/2+graphradius*sin(angle*n));
}

void drawNode(Pimage img,int x, int y,int radius,RGB color){
	int ny;
	int nx;
	for (ny=(y-radius);ny<(y+radius);ny++){
		for (nx=(x-radius);nx<(x+radius);nx++){
			setPixelInImage(img,nx,ny,color);
		}
	}
}

void validateMinMax(int* min,int* max){
	if (*min>*max){
		int tmp=*max;
		*max=*min;
		*min=tmp;
	}
}


void drawNodeLine(Pimage img, int N,int graphRadius,int from, int to, int lineradius, RGB color){
	int fromx=0;
	int fromy=0;
	int tox=0;
	int toy=0;
	int tmp;
	getXYBMP(N,from,graphRadius,img->width,img->height,&fromx,&fromy);
	getXYBMP(N,to,graphRadius,img->width,img->height,&tox,&toy);
	drawLine(img,fromx,fromy,tox,toy,lineradius,color);
}
